/**
 * Tracker
 * <p/>
 * User: joakimd
 * Date: 2013-03-12
 * Time: 17:32
 */
package org.dru.masic.sequencers.tracker {
import org.dru.masic.MasicSequencer;

public final class Tracker extends MasicSequencer {
    private var _song: Song;
    private var _position: int;
    private var _line: int;
    private var _tickInLine: int;

    public function Tracker() {
        _song = new Song();
        _position = 0;
        _line = 0;
        _tickInLine = 0;
        timing.ticksPerBeat = song.linesPerBeat * song.ticksPerLine;
    }

    public function get song(): Song {
        return _song;
    }

    public function get position(): int {
        return _position;
    }

    public function set position(value: int): void {
        _position = value;
    }

    public function get line(): int {
        return _line;
    }

    public function set line(value: int): void {
        if (value < 0) {
            throw new Error("negative value");
        }
        _line = value;
    }

    override public function processTick(): void {
        const pattern: int = song.getSequenceEntry(position);
        for (var tweakTrack: int = song.numTweakTracks; --tweakTrack >= 0;) {
            const tweakEntry: int = song.getTweakEntry(tweakTrack, pattern, line);
            const tweakEntry2: int = song.getTweakEntry(tweakTrack, pattern, line + 1);
            if (tweakEntry != 0xffffff00 && tweakEntry2 != 0xffffff00) {
                const value: Number = Number(tweakEntry) + Number(tweakEntry2 - tweakEntry) * Number(_tickInLine) / Number(song.ticksPerLine);
                const tweakComponent: int = song.getTweakComponent(tweakTrack);
                const tweakParameter: int = song.getTweakParameter(tweakTrack);
                if (tweakComponent >= 0 && tweakComponent < container.numComponents) {
                    container.getComponentAt(tweakComponent).getParameterAt(tweakParameter).value = value / 64.0;
                }
            }
        }
        if (_tickInLine == 0) {
            for (var noteTrack: int = song.numNoteTracks; --noteTrack >= 0;) {
                const noteEntry: int = song.getNoteEntry(noteTrack, pattern, line);
                if (noteEntry != 0xffffff00) {
                    const note: int = (noteEntry >> 24) & 0xff;
                    const component: int = (noteEntry >> 16) & 0xff;
                    const velocity: int = (noteEntry >> 8) & 0xff;
                    const delay: int = noteEntry & 0xff;
                    if (component >= 0 && component < container.numComponents) {
                        container.getComponentAt(component).processNote(note, Number(velocity) / 128.0);
                    }
                }
            }
            line++;
            if (line >= song.getPatternLength(pattern)) {
                line = 0;
                position++;
                if (position >= song.songLength) {
                    position = 0;
                }
            }
        }
        _tickInLine = (_tickInLine + 1) % song.ticksPerLine;
    }
}
}
